package com.ruoyi.file.storage.platform;

import com.ruoyi.file.constant.CommonConstant;
import com.ruoyi.file.domain.po.FileBo;
import com.ruoyi.file.properties.FsServerProperties;
import com.ruoyi.file.storage.IFileStorage;
import com.ruoyi.file.utils.ResponseUtil;
import io.minio.*;
import io.minio.errors.ErrorResponseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;

/**
 * minio 文件上传
 *
 * @Author: 依梦
 * @Date: 2024/11/2
 * @Description: MinioStorage
 */
@Slf4j
@Service
public class MinioStorage implements IFileStorage {

    private final MinioClient minioClient;
    private final String endPoint;
    private final String bucket;

    public MinioStorage() {
        try {
            String accessKey = "B6G54BqXnOxzoSApRmkI";//config.getAccessKey();
            String secretKey = "Xu3zcYh3ivtm0DV4RPMkxSUifbBBRndCDDZt5vvX";//config.getSecretKey();
            String endPoint = "http://122.152.215.206:9000";//config.getEndpoint();
            String bucket = "blog";//config.getBucket();
            this.minioClient = MinioClient.builder()
                    .credentials(accessKey, secretKey)
                    .endpoint(endPoint)
                    .build();
            this.endPoint = endPoint;
            this.bucket = bucket;
        } catch (Exception e) {
            log.error("[Minio] MinioClient build failed: {}", e.getMessage());
            throw new RuntimeException("请检查Minio配置是否正确");
        }
    }


    @Override
    public boolean bucketExists(String bucket) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
        } catch (Exception e) {
            log.error("[Minio] bucketExists Exception:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public void makeBucket(String bucket) {
        try {
            if (!bucketExists(bucket)) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
                log.info("[Minio] makeBucket success bucketName:{}", bucket);
            }
        } catch (Exception e) {
            log.error("[Minio] makeBucket Exception:{}", e.getMessage());
            throw new RuntimeException("创建存储桶失败");
        }
    }

    @Override
    public FileBo upload(MultipartFile file) {
        makeBucket(bucket);
        FileBo fileBo = FileBo.build(file);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucket)
                    .object(fileBo.getFileName())
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();
            minioClient.putObject(putObjectArgs);
            String url = getUrl(fileBo.getFileName());
            fileBo.setUrl(url);
            return fileBo;
        } catch (Exception e) {
            log.error("[Minio] file upload failed: {}", e.getMessage());
            throw new RuntimeException("文件上传失败");
        }
    }

    public FileBo uploadProject(String path, MultipartFile file) {
        makeBucket(bucket);
        // 将上传的文件整理成 FileBo 对象
        FileBo fileBo = FileBo.build(file);
        try {
            InputStream inputStream = file.getInputStream();
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucket)
                    .object(path + fileBo.getFileName())
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();
            minioClient.putObject(putObjectArgs);
            String url = "/prefix" + CommonConstant.DIR_SPLIT + bucket + CommonConstant.DIR_SPLIT + path + fileBo.getFileName();
            fileBo.setUrl(url);
            inputStream.close();
            return fileBo;
        } catch (Exception e) {
            log.error("[Minio] file upload failed: {}", e.getMessage());
            throw new RuntimeException("文件上传失败");
        }
    }

    @Override
    public void delete(String objectName) {
        if (StringUtils.isEmpty(objectName)) {
            throw new RuntimeException("文件删除失败, 文件对象为空");
        }
        try {
            RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
                    .bucket(bucket)
                    .object(objectName)
                    .build();
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
            log.error("[Minio] file delete failed: {}", e.getMessage());
            throw new RuntimeException("文件删除失败");
        }
    }

    @Override
    public void download(String objectName, HttpServletResponse response) {
        if (StringUtils.isEmpty(objectName)) {
            throw new RuntimeException("文件下载失败, 文件对象为空");
        }
        try {
            GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                    .bucket(bucket)
                    .object(objectName)
                    .build();
            GetObjectResponse is = minioClient.getObject(getObjectArgs);
            ResponseUtil.write(is, objectName, response);
            log.info("[Minio] file download success, object:{}", objectName);
        } catch (Exception e) {
            log.error("[Minio] file download failed: {}", e.getMessage());
            throw new RuntimeException("文件下载失败");
        }
    }

    @Override
    public String getUrl(String objectName) {
        return endPoint + CommonConstant.DIR_SPLIT + bucket + CommonConstant.DIR_SPLIT + objectName;
    }

    /**
     * 根据 url
     * 删除对应的文件
     *
     * @param url
     */
    public void deleteUpload(String url) {
        if (StringUtils.isEmpty(url)) {
            throw new RuntimeException("文件删除失败, 文件对象为空");
        }
//        try {
//            RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
//                    .bucket(bucket)
//                    .object(url)
//                    .build();
//            minioClient.removeObject(removeObjectArgs);
//            log.info("minio 文件移除成功");
//        } catch (Exception e) {
//            log.error("[Minio] file delete failed: {}", e.getMessage());
//            throw new RuntimeException("文件删除失败");
//        }
        try {
            // Remove the object
            RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
                    .bucket(bucket)
                    .object(url)
                    .build();
            minioClient.removeObject(removeObjectArgs);
            log.info("minio 文件移除成功");
            // Check if the object still exists
            StatObjectArgs statObjectArgs = StatObjectArgs.builder()
                    .bucket(bucket)
                    .object(url)
                    .build();
            minioClient.statObject(statObjectArgs);
        } catch (ErrorResponseException e) {
            if (e.errorResponse().code().equals("NoSuchKey")) {
                log.info("确认文件已成功移除: " + url);
            } else {
                log.error("检查文件存在时出错: " + e.getMessage());
            }
        } catch (Exception e) {
            log.error("文件移除或检查时出错: " + e.getMessage());
        }
    }


}
